#include "virtual_intc_key.h"

static int virtual_intc_key_probe(struct platform_device *pdev);
static int virtual_intc_key_remove(struct platform_device *pdev);

/* 匹配列表，用于设备树和平台驱动匹配 */
static const struct of_device_id virtual_intc_key_of_match[] = {
	{.compatible = "atk,virtual_intc_key"},
	{ /* Sentinel */ }
};
//平台驱动
static struct platform_driver virtual_intc_key_drv = {
	.driver = {
		.name = "virtual_intc_key",
		.owner = THIS_MODULE,
		.pm = NULL,
		.of_match_table = virtual_intc_key_of_match,
	},
	.probe = virtual_intc_key_probe,
	.remove = virtual_intc_key_remove,
};

static irqreturn_t virtual_intc_key_handler(int irq, void *dev)
{
	struct virtual_intc_key_handle *handle;
	
	handle = dev;
	printk("function:%s line%d name:%s\n", __FUNCTION__, __LINE__, handle->name);

	//返回IRQ_HANDLED，表示中断被成功处理
	return IRQ_HANDLED;
}

//设备和驱动匹配成功执行
static int virtual_intc_key_probe(struct platform_device *pdev)
{
	int result;
	int index;
	struct virtual_intc_key_handle *handle;

	printk("%s\r\n", __FUNCTION__);

	for(index=0; ; index++)
	{
		//分配设备句柄
		handle = devm_kzalloc(&pdev->dev, sizeof(struct virtual_intc_key_handle), GFP_KERNEL);
		if(!handle)
		{
			printk("alloc memory faikey\r\n");
			return -ENOMEM;
		}

		//获取中断号
		handle->irq = of_irq_get(pdev->dev.of_node, index);
		if(handle->irq <= 0)
			break;

		//获取中断触发方式
		handle->irq_flags = irq_get_trigger_type(handle->irq);
		if(handle->irq_flags == IRQF_TRIGGER_NONE)
			handle->irq_flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;

		//注册中断
		snprintf(handle->name, sizeof(handle->name), "virtual_intc_key%d", index);
		result = devm_request_irq(&pdev->dev, handle->irq, virtual_intc_key_handler, handle->irq_flags, handle->name, handle);
		if(result != 0)
		{
			printk("request irq failed\r\n");
			return result;
		}
	}

	return 0;
}

//设备或驱动卸载时执行
static int virtual_intc_key_remove(struct platform_device *pdev)
{
	printk("%s\r\n", __FUNCTION__);

	return 0;
}

static int __init virtual_intc_key_drv_init(void)
{
	int result;

	printk("%s\r\n", __FUNCTION__);

	//注册平台驱动
	result = platform_driver_register(&virtual_intc_key_drv);
	if(result < 0)
	{
		printk("add cdev faikey\r\n");
		return result;
	}

	return 0;
}

static void __exit virtual_intc_key_drv_exit(void)
{
	printk("%s\r\n", __FUNCTION__);

	//注销平台驱动
	platform_driver_unregister(&virtual_intc_key_drv);
}

module_init(virtual_intc_key_drv_init);
module_exit(virtual_intc_key_drv_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("LF");
MODULE_DESCRIPTION("virtual_intc_key_dev");
